package com.zyx.mpdemo.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zyx.mpdemo.common.exception.BusinessException;
import com.zyx.mpdemo.mapper.CourseMapper;
import com.zyx.mpdemo.model.entity.Course;
import com.zyx.mpdemo.model.enums.CourseStatusEnums;
import com.zyx.mpdemo.model.req.BatchLearnedReq;
import com.zyx.mpdemo.model.req.CourseDetailReq;
import com.zyx.mpdemo.model.req.CourseListReq;
import com.zyx.mpdemo.model.vo.CourseDetailVO;
import com.zyx.mpdemo.model.vo.CourseInfoVO;
import com.zyx.mpdemo.model.vo.CourseListVO;
import com.zyx.mpdemo.model.vo.CourseVO;
import com.zyx.mpdemo.service.ICourseService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>针对表【t_course】的数据库操作Service实现</p>
 *
 * @author zhangyaxi
 * @since 2022-11-21 12:12
 */
@Service
public class CourseServiceImpl extends ServiceImpl<CourseMapper, Course> implements ICourseService {

    @Override
    public List<CourseInfoVO> getCourseInfo() {
        List<CourseInfoVO> courseInfos = new ArrayList<>();
        QueryWrapper<Course> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("distinct course_id, course_name, chapter")
            .ne("course_status", CourseStatusEnums.DELETE);
        List<Course> courses = list(queryWrapper);
        Map<Long, List<Course>> courseMap = courses.stream().collect(Collectors.groupingBy(Course::getCourseId));
        List<Long> courseIds = new ArrayList<>(courseMap.keySet());
        courseIds.sort(Long::compareTo);
        for (Long courseId : courseIds) {
            List<Course> coursesById = courseMap.get(courseId);
            if (CollUtil.isNotEmpty(coursesById)) {
                String courseName = coursesById.get(0).getCourseName();
                Set<String> chapters = coursesById.stream().map(Course::getChapter).collect(Collectors.toSet());
                courseInfos.add(new CourseInfoVO().setCourseId(courseId).setCourseName(courseName).setChapters(chapters));
            }
        }
        return courseInfos;
    }


    @Override
    public List<CourseDetailVO> getCourseDetail(CourseDetailReq courseDetailReq) {
        List<CourseDetailVO> courseDetails = new ArrayList<>();
        String courseName = courseDetailReq.getCourseName();
        LambdaQueryWrapper<Course> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper
            .eq(Course::getCourseName, courseName)
            .ne(Course::getCourseStatus, CourseStatusEnums.DELETE);
        boolean needChapter = courseDetailReq.isNeedChapter();
        Set<String> chapters = courseDetailReq.getChapters();
        if (!needChapter) {
            // 不需要分组
            List<Course> courses = list(queryWrapper);
            courseDetails.add(CourseDetailVO.getCourseDetail(courseName, "all", courses));
        } else {
            // 需要分组
            queryWrapper.in(CollUtil.isNotEmpty(chapters), Course::getChapter, chapters);
            List<Course> courses = list(queryWrapper);
            courseDetails.addAll(CourseDetailVO.getCourseDetails(courseName, courses));
        }
        return courseDetails;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchLearned(BatchLearnedReq batchLearnedReq) {
        LambdaQueryWrapper<Course> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper
            .eq(Course::getCourseName, batchLearnedReq.getCourseName())
            .eq(Course::getChapter, batchLearnedReq.getChapter())
            .ge(Course::getSequence, batchLearnedReq.getStartSeq())
            .le(Course::getSequence, batchLearnedReq.getEndSeq())
            .ne(Course::getCourseStatus, CourseStatusEnums.DELETE);
        List<Course> updateCourses = list(queryWrapper).stream()
            .filter(it -> it.getCourseStatus().equals(CourseStatusEnums.LEARNING))
            .peek(it -> {
                it.setCourseStatus(CourseStatusEnums.LEARNED);
                it.setUpdateTime(null);
            })
            .collect(Collectors.toList());
        if (CollUtil.isEmpty(updateCourses)) {
            throw new BusinessException("当前课程及章节下不存在未学习的内容");
        }
        updateBatchById(updateCourses);
    }

    @Override
    public CourseListVO getCourseList(CourseListReq courseListReq) {
        Long courseId = courseListReq.getCourseId();
        Integer status = courseListReq.getStatus();
        String chapter = courseListReq.getChapter();
        LambdaQueryWrapper<Course> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper
            .eq(Course::getCourseId, courseId);
        if (Objects.isNull(status) || Objects.equals(status, 0)) {
            queryWrapper.ne(Course::getCourseStatus, CourseStatusEnums.DELETE);
        } else {
            CourseStatusEnums courseStatus = CourseStatusEnums.of(status);
            queryWrapper.eq(Course::getCourseStatus, courseStatus);
        }
        queryWrapper.eq(StrUtil.isNotEmpty(chapter), Course::getChapter, chapter);
        List<Course> courses = list(queryWrapper);
        if (CollUtil.isEmpty(courses)) {
            throw new BusinessException("不存在当前的课程");
        }
        String courseName = courses.get(0).getCourseName();
        TreeMap<String, List<CourseVO>> courseMap = courses.stream()
            .map(Course::toCourseVO)
            .collect(Collectors.groupingBy(CourseVO::getChapter, TreeMap::new, Collectors.toList()));
        return new CourseListVO().setCourseId(courseId).setCourseName(courseName).setCourseMap(courseMap);
    }

}
